import random
from vector import Vector


class Matrix(object):
    # 矩阵的初始化
    def __init__(self, matrix, w, h):
        self.__matrix = matrix
        self.__width = w
        self.__height = h

    # 返回矩阵的字符表达形式
    def __str__(self):
        ans = ""
        for i in range(self.__height):
            ans += "|"
            for j in range(self.__width):
                if j < self.__width - 1:
                    ans += str(self.__matrix[i][j]) + ","
                else:
                    ans += str(self.__matrix[i][j]) + "|\n"
        return ans

    # 改变矩阵特定位置的元素
    def change_component(self, x, y, value):  # 改变矩阵特定位置的元素
        if 0 <= x < self.__height and 0 <= y < self.__width:
            self.__matrix[x][y] = value
        else:
            raise Exception("changeComponent: indices out of bounds")

    # 返回矩阵特定位置的元素
    def component(self, x, y):
        if 0 <= x < self.__height and 0 <= y < self.__width:
            return self.__matrix[x][y]
        else:
            raise Exception("changeComponent: indices out of bounds")

    # 返回矩阵的宽度
    def width(self):
        return self.__width

    # 返回矩阵的高度
    def height(self):
        return self.__height

    # 矩阵的乘积
    def __mul__(self, other):
        if isinstance(other, Vector):  # 判断与矩阵乘积的对象是向量
            if len(other) == self.__width:
                ans = Vector.zero_vector(self.__height)
                for i in range(self.__height):
                    summe = 0
                    for j in range(self.__width):
                        summe += other.component(j) * self.__matrix[i][j]
                    ans.changeComponent(i, summe)
                    summe = 0
                return ans
            else:
                raise Exception("vector must have the same size as the " + "number of columns of the matrix!")
        elif isinstance(other, int) or isinstance(other, float):  # 判断与矩阵乘积的是标量，即数乘
            matrix = [[self.__matrix[i][j] * other for j in range(self.__width)] for i in range(self.__height)]
            return Matrix(matrix, self.__width, self.__height)

    # 矩阵的加法
    def __add__(self, other):
        if self.__width == other.width() and self.__height == other.height():
            matrix = []
            for i in range(self.__height):
                row = []
                for j in range(self.__width):
                    row.append(self.__matrix[i][j] + other.component(i, j))
                matrix.append(row)
            return Matrix(matrix, self.__width, self.__height)
        else:
            raise Exception("matrix must have the same dimension!")

    # 矩阵的减法
    def __sub__(self, other):
        if self.__width == other.width() and self.__height == other.height():
            matrix = []
            for i in range(self.__height):
                row = []
                for j in range(self.__width):
                    row.append(self.__matrix[i][j] - other.component(i, j))
                matrix.append(row)
            return Matrix(matrix, self.__width, self.__height)
        else:
            raise Exception("matrix must have the same dimension!")

    # 随机矩阵生成
    def random_matrix(width, height, a, b):
        # 随机矩阵的元素在(a,b)范围内，矩阵宽为 W,矩阵高为 H
        random.seed(None)
        matrix = [[random.randint(a, b) for j in range(width)] for i in range(height)]
        return Matrix(matrix, width, height)
